/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 simulated_combat.h

	$Header: /heroes4/simulated_combat.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( SIMULATED_COMBAT_H_INCLUDED )
#define SIMULATED_COMBAT_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <list>
#include "adv_map_point.h"
#include "army_ptr.h"
#include "artifact.h"
#include "creature_array.h"
#include "map_point.h"
#include "owned_ptr.h"
#include "simulated_combat_creature_ptr.h"

class  t_abstract_grail_data_source;
struct t_adv_map_point;
class  t_adventure_map;
class  t_adventure_frame;
enum   t_combat_result;
class  t_player;
enum   t_spell;
class  t_town;
class  t_window;

class t_simulated_combat_creature_list : public std::list<t_simulated_combat_creature_ptr>
{
};

// -----------------------------------------------------------
// class which depicts a simulate combat between two sides
// -----------------------------------------------------------
class t_simulated_combat
{
public:
	t_simulated_combat( t_creature_array&		attacker,
						t_player*				attacking_player, 
						t_creature_array&		defenders,
						t_player*				defending_player,
						t_adventure_map&		adventure_map,
						t_adv_map_point const&	location,
						t_town*					town );
	t_simulated_combat( t_creature_array**	armies,
						t_player**			players,
						t_town*				town,
						bool				sea_battle,
						t_abstract_grail_data_source const& attacker_grail_data,
						t_abstract_grail_data_source const& defender_grail_data );
	~t_simulated_combat();

	void					add( t_simulated_combat_creature* creature );
	void					enable_spellcasting( bool side, bool arg );
	void					finalize_combat( t_adventure_frame* window,
											 bool const * are_real_armies, 
											 t_army_ptr & new_army_ptr );
	t_creature_array const*	get_losses() const;
	t_combat_result			get_result() const;
	int						get_turns() const;
	float					query_combat_value() const;
	float					query_value_drop() const;
	void					update_attacking_force();
	void					run();
	void					record_results( t_adventure_frame* frame );
	void					report_results( t_adventure_frame* frame );
	void					set_effectiveness( bool defender, double effectiveness );
protected:
	void						 cast_damage( t_simulated_combat_creature& caster,
											  t_spell					   spell,
											  t_simulated_combat_creature& target );
	void						 cast_spell( t_simulated_combat_creature& caster,
											 t_spell					  spell,
									         t_simulated_combat_creature* target,
											 t_simulated_combat_creature* client = 0 );
	void						 cast_summoning( t_simulated_combat_creature& caster,
												 t_spell					  spell );
	bool						 choose_action( t_simulated_combat_creature& attacker );
	int							 choose_damage_target( t_simulated_combat_creature const& caster,
													   t_spell							  spell,
													   t_simulated_combat_creature*&	  best_target );
	int							 choose_sacrifice_target( t_simulated_combat_creature const& caster,
												          t_simulated_combat_creature*&		best_target,
												          t_simulated_combat_creature*&		best_client );
	int							 choose_spell( t_simulated_combat_creature const& attacker,
											   t_spell&							  best_spell,
											   t_simulated_combat_creature*&	  best_target,
											   t_simulated_combat_creature*&	  best_client );
	int							 choose_spell_target( t_simulated_combat_creature const& attacker,
													  t_spell							 spell,
													  t_simulated_combat_creature*&		 best_target );
	int							 choose_spell_target( t_simulated_combat_creature const& attacker,
													  t_spell							 spell,
													  t_simulated_combat_creature*&		 best_target,
													  t_simulated_combat_creature*&		 best_client );
	int							 get_mass_spell_value( t_simulated_combat_creature const& caster,
											            t_spell							   spell ) const;
	int							 get_spell_target_value( t_simulated_combat_creature const& attacker,
														 t_spell							spell,
														 t_simulated_combat_creature const& target ) const;
	void							initialize();
	t_simulated_combat_creature*	select_next_creature( bool last_was_defender );

	t_creature_array*					m_armies[2];
	t_artifact_list						m_booty; // Artifacts left over from destroyed armies
	t_simulated_combat_creature_list	m_creatures;
	t_owned_ptr<t_abstract_grail_data_source> m_grail_data[2];
	bool								m_has_magic[2];
	t_creature_stack_ptr				m_leaders[2];
	t_adv_map_point						m_location;
	t_creature_array					m_losses[2];
	t_player*							m_players[2];
	t_combat_result						m_result;
	bool								m_sea_battle;
	bool								m_spellcasting_allowed[2];
	double								m_tactics_defense_bonus[2];
	double								m_tactics_offense_bonus[2];
	t_town*								m_town;
	int									m_turns;
};

inline void t_simulated_combat::enable_spellcasting( bool side, bool arg )
{
	m_spellcasting_allowed[side] = arg;
}

inline t_combat_result t_simulated_combat::get_result() const
{
	return m_result;
}

inline int t_simulated_combat::get_turns() const
{
	return m_turns;
}

#endif
